
package com.probiz.estore.system.scheduler.web;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.quartz.CronTrigger;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleTrigger;
import org.quartz.Trigger;
import org.springframework.web.servlet.ModelAndView;

import com.probiz.estore.core.controller.BaseController;
import com.probiz.estore.core.util.SchedulerUtil;

public class SchedulerController extends BaseController {


	private Scheduler	scheduler		= null;

	/** 是否为EAI同步后台任务，当scheduler为bean eaiScheduler时 */
	private boolean		isEaiScheduler	= false;
	
	private static final String	TYPE_SIMPLE_TRIGGER	= "SimpleTrigger";
	private static final String	TYPE_CRON_TRIGGER	= "CronTrigger";

	private String		listView		= "system/schedulerList";
	private String		formView		= "system/schedulerTriggerForm";

	public void setIsEaiScheduler(boolean isEaiScheduler) {
		this.isEaiScheduler = isEaiScheduler;
	}

	public ModelAndView defaultAction(HttpServletRequest req, HttpServletResponse resp) throws ServletException {
		return getBaseMv();
	}

	public ModelAndView run(HttpServletRequest req, HttpServletResponse resp) {
		boolean hasError = false;
		try {
			SchedulerUtil.startupScheduler(scheduler);
		} catch (SchedulerException e) {
			logger.error("Can't start scheduler.", e);
			hasError = true;
		}
		ModelAndView mv = getBaseMv();
		if (hasError) {
			saveMessage(req, getMessage("scheduler.error.start"));
			// mv.addObject("errorMsg", "Can't start scheduler.");
		}
		return mv;
	}

	public ModelAndView stop(HttpServletRequest req, HttpServletResponse resp) {
		boolean hasError = false;
		try {
			scheduler.standby();
		} catch (SchedulerException e) {
			logger.error("Can't shutdown scheduler.", e);
			hasError = true;
		}
		ModelAndView mv = getBaseMv();
		if (hasError) {
			saveMessage(req, getMessage("scheduler.error.shutdown"));
			// mv.addObject("errorMsg", "Can't shutdown scheduler.");
		}
		return mv;
	}

	public ModelAndView pausedTrigger(HttpServletRequest req, HttpServletResponse resp) {
		String triggerName = req.getParameter("trigger");
		String groupName = req.getParameter("group");
		boolean hasError = false;
		try {
			scheduler.pauseTrigger(triggerName, groupName);
			SchedulerUtil.pausedTriggerInConfig(triggerName, isEaiScheduler);
		} catch (Exception e) {
			logger.error("Can't shutdown scheduler.", e);
			hasError = true;
		}
		ModelAndView mv = getBaseMv();
		if (hasError) {
			saveMessage(req, getMessage("scheduler.error.paused", new Object[] { triggerName }));
			// mv.addObject("errorMsg", "Can't paused trigger["+ triggerName
			// +"].");
		}
		return mv;
	}

	public ModelAndView resumeTrigger(HttpServletRequest req, HttpServletResponse resp) {
		String triggerName = req.getParameter("trigger");
		String groupName = req.getParameter("group");
		boolean hasError = false;
		try {
			scheduler.resumeTrigger(triggerName, groupName);
			SchedulerUtil.unpausedTriggerInConfig(triggerName, isEaiScheduler);
		} catch (Exception e) {
			logger.error("Can't shutdown scheduler.", e);
			hasError = true;
		}
		ModelAndView mv = getBaseMv();
		if (hasError) {
			saveMessage(req, getMessage("scheduler.error.resume", new Object[] { triggerName }));
			// mv.addObject("errorMsg", "Can't resume trigger["+ triggerName
			// +"].");
		}
		return mv;
	}


	private ModelAndView getBaseMv() {
		ModelAndView mv = new ModelAndView(listView);
		mv.addObject("isEaiScheduler", isEaiScheduler);
		mv.addObject("scheduler", scheduler);


		String[] triggerGroups;
		String[] triggersInGroup;
		try {
			if (scheduler.isInStandbyMode()) {
				return mv;
			}
			triggerGroups = scheduler.getTriggerGroupNames();
			int groupSize = triggerGroups.length;
			mv.addObject("groupSize", groupSize);
			for (int i = 0; i < triggerGroups.length; i++) {
				mv.addObject("groupName" + i, triggerGroups[i]);
				triggersInGroup = scheduler.getTriggerNames(triggerGroups[i]);

				List triggers = new ArrayList();
				for (int j = 0; j < triggersInGroup.length; j++) {
					TriggerModel tmodel = new TriggerModel();
					Trigger trigger = scheduler.getTrigger(triggersInGroup[j], triggerGroups[i]);
					// 添加描述，去掉原来在trigger中的描述的 pasused_flag
					String des = trigger.getDescription();
					if (des != null) {
						while (des.endsWith(SchedulerUtil.PAUSED_FLAG)) {
							des = des.substring(0, des.indexOf(SchedulerUtil.PAUSED_FLAG));
						}
					}
					trigger.setDescription(des);
					tmodel.setTrigger(trigger);
					int status = scheduler.getTriggerState(triggersInGroup[j], triggerGroups[i]);
					// 如果发现执行job有错误,而且不是暂停状态,则设置为ERROR状态显示.
					if (SchedulerUtil.hasErrorTrigger(triggersInGroup[j]) && status != Trigger.STATE_PAUSED) {
						tmodel.setStatus(Trigger.STATE_ERROR);
					} else {
						tmodel.setStatus(status);
					}
					triggers.add(tmodel);
				}
				mv.addObject("groupTriggers" + i, triggers);
			}
		} catch (SchedulerException e) {
			logger.error("Get scheduler fail.", e);
		}

		return mv;
	}
	
	
	public ModelAndView edit(HttpServletRequest req, HttpServletResponse resp) throws ServletException {
		ModelAndView mv = new ModelAndView(formView);
		Trigger trigger = getTrigger(req);
		if (trigger instanceof CronTrigger) {
			mv.addObject("triggerType", TYPE_CRON_TRIGGER);
		} else if (trigger instanceof SimpleTrigger) {
			mv.addObject("triggerType", TYPE_SIMPLE_TRIGGER);
		}
		mv.addObject("trigger", trigger);
		mv.addObject("isEaiScheduler", isEaiScheduler);
		return mv;
	}

	/**
	 * save the trigger.
	 * 
	 * @param req
	 * @param resp
	 * @return
	 */
	public ModelAndView save(HttpServletRequest req, HttpServletResponse resp) {
		Trigger trigger = getTrigger(req);
		if (trigger instanceof CronTrigger) {
			return saveCronTrigger(req, (CronTrigger) trigger);
		} else if (trigger instanceof SimpleTrigger) {
			return saveSimpleTrigger(req, (SimpleTrigger) trigger);
		}
		return null;
	}

	private ModelAndView saveCronTrigger(HttpServletRequest req, CronTrigger trigger) {
		String cronExpression = req.getParameter("cronExpression");
		ModelAndView mv = new ModelAndView(formView);
		mv.addObject("trigger", trigger);
		mv.addObject("triggerType", TYPE_CRON_TRIGGER);
		mv.addObject("isEaiScheduler", isEaiScheduler);

		try {
			trigger.setCronExpression(cronExpression);
		} catch (java.text.ParseException e) {
			saveMessage(req, getMessage("scheduler.error.expression"));
			return mv;
		}
		if (!reSchedulerJob(trigger)) {
			saveMessage(req, getMessage("scheduler.error.reScheduler"));
			return mv;
		}
		try {
			SchedulerUtil.updateCronTriggerConfig(trigger.getName(), cronExpression, isEaiScheduler);
		} catch (Exception e) {
			saveMessage(req, getMessage("scheduler.error.updateConfig"));
			logger.error("Can't not update XML File.", e);
		}
		
		saveMessage(req, getMessage("scheduler.trigger.updtate.success", new Object[]{trigger.getJobName()}));
		
		return mv;
	}

	private ModelAndView saveSimpleTrigger(HttpServletRequest req, SimpleTrigger trigger) {
		long repeatInterval = 0;

		ModelAndView mv = new ModelAndView(formView);
		mv.addObject("triggerType", TYPE_SIMPLE_TRIGGER);
		mv.addObject("trigger", trigger);
		mv.addObject("isEaiScheduler", isEaiScheduler);
		try {
			repeatInterval = Long.parseLong(req.getParameter("repeatInterval"));
		} catch (NumberFormatException e) {
			saveMessage(req, getMessage("scheduler.error.invalidParam"));
			return mv;
		}

		trigger.setRepeatInterval(repeatInterval);
		if (!reSchedulerJob(trigger)) {
			saveMessage(req, getMessage("scheduler.error.reScheduler"));
			return mv;
		}
		try {
			SchedulerUtil.updateSimpleTriggerConfig(trigger.getName(), repeatInterval, isEaiScheduler);
		} catch (Exception e) {
			saveMessage(req, getMessage("scheduler.error.updateConfig"));
			logger.error("Can't not update XML File.", e);
		}
		
		saveMessage(req, getMessage("scheduler.trigger.updtate.success", new Object[]{trigger.getJobName()}));
		
		return mv;
	}

	private boolean reSchedulerJob(Trigger trigger) {
		boolean rs = true;
		try {
			int status = scheduler.getTriggerState(trigger.getName(), trigger.getGroup());
			scheduler.unscheduleJob(trigger.getName(), trigger.getGroup());
			scheduler.scheduleJob(trigger);
			if (status == 0) {
				scheduler.resumeTrigger(trigger.getName(), trigger.getGroup());
			}
		} catch (SchedulerException e) {
			rs = false;
			logger.error("Can't not reset trigger[" + trigger.getName() + "]", e);
		}
		return rs;
	}

	private Trigger getTrigger(HttpServletRequest req) {
		String trigger = req.getParameter("trigger");
		String group = req.getParameter("group");
		Trigger rs = null;
		try {
			rs = scheduler.getTrigger(trigger, group);
		} catch (SchedulerException e) {
			logger.error("Get trigger fail.", e);
		}
		// 处理描述文字
		String des = rs.getDescription();
		while (des.endsWith(SchedulerUtil.PAUSED_FLAG)) {
			des = des.substring(0, des.indexOf(SchedulerUtil.PAUSED_FLAG));
		}
		rs.setDescription(des);
		return rs;
	}

	public class TriggerModel {
		private Trigger	trigger	= null;
		private int		status	= 0;

		public int getStatus() {
			return status;
		}

		public void setStatus(int status) {
			this.status = status;
		}

		public Trigger getTrigger() {
			return trigger;
		}

		public void setTrigger(Trigger trigger) {
			this.trigger = trigger;
		}
	}

	public void setScheduler(Scheduler avalue) {
		scheduler = avalue;
	}
	
	

}
